/*****************************************************************************
 * hal_hi_uart.c
 *
 * Copyright (C) 2019 Jeasonvor <1101627719@qq.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 ****************************************************************************/

/*****************************************************************************
 * Included Files
 ****************************************************************************/

#include "plum_api.h"
#include "hal/source/hal_hi/hal_hi.h"

/*****************************************************************************
 * Trace Definitions
 ****************************************************************************/
#define LOG_RUN_LEVEL LOG_LEVEL_DEBUG
#define LOG_MODULE    "hal.uart"
#include "thirdparty/log/log.h"
/*****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/*****************************************************************************
 * Private Types
 ****************************************************************************/

/*****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

/*****************************************************************************
 * Private Data
 ****************************************************************************/

/*****************************************************************************
 * Public Data
 ****************************************************************************/

/*****************************************************************************
 * Private Functions
 ****************************************************************************/

PLUM_PRIVATE
hi_u32 hal_hi_idx(plum_u32 id)
{
    hi_u32 idx = HI_UART_IDX_MAX;

    switch (PLUM_HAL_UART_IDX(id)) {
        case 0:
            idx = HI_UART_IDX_0;
            break;
        case 1:
            idx = HI_UART_IDX_1;
            break;
        case 2:
            idx = HI_UART_IDX_2;
            break;
    }

    return (idx);
}

PLUM_PRIVATE
hi_u8 hal_uart_databits(plum_hal_uart_databit_t databits)
{
    hi_u8 dts = HI_UART_DATA_BIT_8;

    switch (databits) {
        case PLUM_HAL_UART_DATABIT_5:
            dts = HI_UART_DATA_BIT_5;
            break;
        case PLUM_HAL_UART_DATABIT_6:
            dts = HI_UART_DATA_BIT_6;
            break;
        case PLUM_HAL_UART_DATABIT_7:
            dts = HI_UART_DATA_BIT_7;
            break;
        case PLUM_HAL_UART_DATABIT_8:
            dts = HI_UART_DATA_BIT_8;
            break;
        case PLUM_HAL_UART_DATABIT_9:
        default:
            break;
    }

    return (dts);
}

PLUM_PRIVATE
hi_u8 hal_uart_parity(plum_hal_uart_parity_t parity)
{
    hi_u8 pt = HI_UART_PARITY_NONE;

    switch (parity) {
        case PLUM_HAL_UART_PARITY_NONE:
            pt = HI_UART_PARITY_NONE;
            break;
        case PLUM_HAL_UART_PARITY_ODD:
            pt = HI_UART_PARITY_ODD;
            break;
        case PLUM_HAL_UART_PARITY_EVEN:
            pt = HI_UART_PARITY_EVEN;
            break;
        default:
            break;
    }

    return (pt);
}

PLUM_PRIVATE
hi_u8 hal_uart_stopbit(plum_hal_uart_stopbit_t stopbits)
{
    hi_u8 sb = HI_UART_STOP_BIT_1;

    switch (stopbits) {
        case PLUM_HAL_UART_STOPBIT_1:
            sb = HI_UART_STOP_BIT_1;
            break;
        case PLUM_HAL_UART_STOPBIT_2:
            sb = HI_UART_STOP_BIT_2;
            break;
        case PLUM_HAL_UART_STOPBIT_0_5:
        case PLUM_HAL_UART_STOPBIT_1_5:
        default:
            break;
    }

    return (sb);
}

PLUM_PRIVATE
hi_flow_ctrl hal_uart_flow_ctrl(plum_hal_uart_flow_ctrl_t ctrl)
{
    hi_flow_ctrl hfc = HI_FLOW_CTRL_NONE;

    switch (ctrl) {
        case PLUM_HAL_UART_FLOW_CTRL_NONE:
            hfc = HI_FLOW_CTRL_NONE;
            break;
        case PLUM_HAL_UART_FLOW_CTRL_CTS:
            hfc = HI_FLOW_CTRL_CTS_ONLY;
            break;
        case PLUM_HAL_UART_FLOW_CTRL_RTS:
            hfc = HI_FLOW_CTRL_RTS_ONLY;
            break;
        case PLUM_HAL_UART_FLOW_CTRL_RTS_CTS:
            hfc = HI_FLOW_CTRL_RTS_CTS;
            break;
        default:
            break;
    }

    return (hfc);
}

PLUM_PRIVATE
plum_u8 hal_uart_gpio_func(plum_u32 id)
{
    plum_u8 func = HI_IO_FUNC_GPIO_0_UART1_TXD;

    switch (PLUM_HAL_UART_IDX(id)) {
        case 0:
            func = HI_IO_FUNC_GPIO_0_UART1_TXD;
            break;
        case 1:
            func = HI_IO_FUNC_GPIO_1_UART1_RXD;
            break;
        case 3:
            func = HI_IO_FUNC_GPIO_3_UART0_TXD;
            break;
        case 4:
            func = HI_IO_FUNC_GPIO_4_UART0_RXD;
            break;
        case 5:
            func = HI_IO_FUNC_GPIO_5_UART1_RXD;
            break;
        case 6:
            func = HI_IO_FUNC_GPIO_6_UART1_TXD;
            break;
        case 11:
            func = HI_IO_FUNC_GPIO_11_UART2_TXD;
            break;
        case 12:
            func = HI_IO_FUNC_GPIO_12_UART2_RXD;
            break;
        case 13:
            func = HI_IO_FUNC_GPIO_13_UART0_TXD;
            break;
        case 14:
            func = HI_IO_FUNC_GPIO_14_UART0_RXD;
            break;
        default:
            break;
    }

    return (func);
}

PLUM_PRIVATE
hi_io_name hal_uart_gpio_name(plum_u32 id)
{
    hi_io_name name = HI_IO_NAME_MAX;

    switch (PLUM_HAL_UART_IDX(id)) {
        case 0:
            name = HI_IO_NAME_GPIO_0;
            break;
        case 1:
            name = HI_IO_NAME_GPIO_1;
            break;
        case 2:
            name = HI_IO_NAME_GPIO_2;
            break;
        case 3:
            name = HI_IO_NAME_GPIO_3;
            break;
        case 4:
            name = HI_IO_NAME_GPIO_4;
            break;
        case 5:
            name = HI_IO_NAME_GPIO_5;
            break;
        case 6:
            name = HI_IO_NAME_GPIO_6;
            break;
        case 7:
            name = HI_IO_NAME_GPIO_7;
            break;
        case 8:
            name = HI_IO_NAME_GPIO_8;
            break;
        case 9:
            name = HI_IO_NAME_GPIO_9;
            break;
        case 10:
            name = HI_IO_NAME_GPIO_10;
            break;
        case 11:
            name = HI_IO_NAME_GPIO_11;
            break;
        case 12:
            name = HI_IO_NAME_GPIO_12;
            break;
        case 13:
            name = HI_IO_NAME_GPIO_13;
            break;
        case 14:
            name = HI_IO_NAME_GPIO_14;
            break;
        default:
            break;
    }
    return (name);
}
/*****************************************************************************
 * Public Functions
 ****************************************************************************/

PLUM_PUBLIC
plum_s32 plum_hal_uart_init(plum_u32 id, plum_hal_uart_cof_t *config)
{
    plum_s32 rc = PLUM_ECODE_OK;

    // steps_1:  gpio初始化
    hi_io_set_func(hal_uart_gpio_name(config->rxpin_id),
                   hal_uart_gpio_func(config->rxpin_id));
    hi_io_set_func(hal_uart_gpio_name(config->txpin_id),
                   hal_uart_gpio_func(config->txpin_id));

    // steps_2:  串口参数初始化
    hi_uart_attribute attr = {0};
    attr.baud_rate         = config->baudrate;
    attr.data_bits         = hal_uart_databits(config->databit);
    attr.stop_bits         = hal_uart_stopbit(config->stopbit);
    attr.parity            = hal_uart_parity(config->parity);

    hi_uart_extra_attr exattr = {0};
    exattr.rx_buf_size        = config->rxbuf_size;
    rc                        = hi_uart_init(hal_hi_idx(id), &attr, &exattr);
    if (rc) {
        LOG_E("hi_uart_init err,rc:0x%08X", rc);
        rc = PLUM_ECODE_EIO;
    }

    return (rc);
}

PLUM_PUBLIC
plum_s32 plum_hal_uart_send(plum_u32 id, const plum_void *data, plum_u16 cnt)
{
    plum_s32 rc = PLUM_ECODE_OK;

    rc = hi_uart_write(hal_hi_idx(id), (const hi_u8 *)data, cnt);
    if (rc < 0) {
        LOG_E("hi_uart_write err,rc:0x%08X", rc);
        rc = PLUM_ECODE_EIO;
    }

    return (rc);
}

PLUM_PUBLIC
plum_s32 plum_hal_uart_recv(plum_u32 id, void *data, plum_u16 size,
                            plum_u32 timeout)
{
    plum_s32 rc = PLUM_ECODE_OK;

    rc = hi_uart_read_timeout(hal_hi_idx(id), (hi_u8 *)data, size, timeout);
    if (rc < 0) {
        LOG_E("hi_uart_read_timeout err,rc:0x%08X", rc);
        rc = PLUM_ECODE_EIO;
    }

    return (rc);
}

/****************************************************************************/
/*                                                                          */
/*  End of file.                                                            */
/*                                                                          */
/****************************************************************************/
